%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2019, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 23. 12月 2019 13:10
%%%-------------------------------------------------------------------
-module(sys_util).

-compile(export_all).
-compile(nowarn_export_all).

-author("Administrator").
-include("../include/protocol.hrl").
-include("../include/uri.hrl").
-include("../include/player.hrl").
-include("../include/game.hrl").
-include("../include/myshare.hrl").
-include("../include/logger.hrl").

-define(SECONDS_FROM_0_TO_1970, 62167219200).
%% API


%%后台服务器get请求
httpBackendGetRequest(Url) ->
  {ok, ConnPid} = gun:open(myshare:get_env(game_backend_domain), myshare:get_env(game_backend_port)),
  {ok, _} = gun:await_up(ConnPid),
  StreamRef = gun:get(ConnPid, Url),
  Response =
    case gun:await(ConnPid, StreamRef) of
      {response, fin, Status, _Headers} ->
        {no_data, Status, <<>>};
      {response, nofin, Status, _Headers} ->
        {ok, Content} = gun:await_body(ConnPid, StreamRef),
        {ok, Status, Content}
    end,
  gun:close(ConnPid),
  case Response of
    {ok, 200, Res} -> Res;
    _ -> error
  end.


%% http get请求
httpGetRequest(Url) ->
  {ok, ConnPid} = gun:open(myshare:get_env(http_host), myshare:get_env(http_port)),
  {ok, _} = gun:await_up(ConnPid),
  StreamRef = gun:get(ConnPid, Url),
  Response =
    case gun:await(ConnPid, StreamRef) of
      {response, fin, Status, _Headers} ->
        {no_data, Status, <<>>};
      {response, nofin, Status, _Headers} ->
        {ok, Content} = gun:await_body(ConnPid, StreamRef),
        {ok, Status, Content}
    end,
  gun:close(ConnPid),
  Response.
%%http post请求
http_post_request(Url, Body) ->
  ?INFO("request============== http url:~p;body:~p", [Url, Body]),
  try
    Host = myshare:get_env(http_host),
    Port = myshare:get_env(http_port),
    {ok, ConnPid} = gun:open(Host, Port),
    {ok, _} = gun:await_up(ConnPid),
    StreamRef = gun:post(ConnPid, Url, [
%%      {<<"content-length">>, integer_to_binary(length(Body))},
      {<<"content-type">>, "application/x-www-form-urlencoded"}
    ]),
    gun:data(ConnPid, StreamRef, fin, Body),
    Response =
      case gun:await(ConnPid, StreamRef) of
        {response, fin, _Status, _Headers} ->
          throw(no_data);
        {response, nofin, Status, _Headers} ->
          case Status =:= 200 of
            true ->
              {ok, Content} = gun:await_body(ConnPid, StreamRef),
              ResMap = jsx:decode(Content, [return_maps, {labels, atom}]),
              {ok, Code} = maps:find(code, ResMap),
              if
                Code =:= 0 -> {ok, Content};
                true ->
                  ?INFO("server errror~ts", [Content]),
                  throw(server_error)
              end;
            _ -> throw(status_error)
          end
      end,
    gun:close(ConnPid),
    ?INFO("Response:================~p ~n", [Response]),
    Response
  catch
    no_data ->
      ?ERROR("http request error:no_data"),
      {error, no_data};
    status_error ->
      ?ERROR("http request error:status_error"),
      {error, status_error};
    server_error ->
      ?ERROR("http request error:server_error"),
      {error, server_error};
    _ ->
      ?ERROR("http request error"),
      {error, other}
  end.

%%record2json(Map) ->
%%
%%  JsonString = map2json(Map),
%%  binary_to_list(JsonString).

%% map转json string
map2json(Map) ->
  Map1 = maps:remove('__name__', Map),
  Map2 = list2binary(maps:to_list(Map1)),
  JsonString = jsx:encode(Map2),
  binary_to_list(JsonString).

%% list value 转 binary
list2binary(List) ->
  Predicate = fun(Value, NewList) ->
    {Key, Val} = Value,
    NewValue =
      case is_list(Val) of
        true -> {Key, list_to_binary(Val)};
        _ -> Value
      end,
    lists:append(NewList, [NewValue])
              end,
  lists:foldl(Predicate, [], List).

%% map 转 form-data 参数字符串
map2formBinary(Map) ->
  Map1 = maps:remove('__name__', Map),
  List = maps:to_list(Map1),

  String2 = lists:foldl(fun(Value, String) ->
    {Key, Val} = Value,
    NewKey = atom_to_list(Key),
    NewVal = case is_integer(Val) of
               true -> integer_to_list(Val);
               _ -> Val
             end,
    String ++ "&" ++ NewKey ++ "=" ++ NewVal
                        end, "", List),
  list_to_binary(String2).

%%系统时间戳
timestamp() ->
  {M, S, _} = os:timestamp(),
  M * 1000000 + S.

%time转当日datetime
time_to_date_time(Time) ->
  {Date, _} = local_time(),
  {Date, Time}.

% 本地时间
local_time() ->
  calendar:local_time().

% 世界时间
world_time() ->
  calendar:universal_time().

% 时间转时间戳，格式：{{2013,11,13}, {18,0,0}}
datetime_to_timestamp(DateTime) ->
  calendar:datetime_to_gregorian_seconds(DateTime) -
    calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}) -
    3600 * 8.

% 时间戳转时间
timestamp_to_datetime(Timestamp) ->
  calendar:gregorian_seconds_to_datetime(Timestamp +
    calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})).

date_string_to_datetime(String) ->
  [Date, Time] = string:tokens(String, " "),
  [Y, M, D] = string:tokens(Date, "-"),
  [H, I, S] = string:tokens(Time, ":"),
  {{list_to_integer(Y), list_to_integer(M), list_to_integer(D)}, {list_to_integer(H), list_to_integer(I), list_to_integer(S)}}.

date_string_to_timestamp(String) ->
  Date = date_string_to_datetime(String),
  datetime_to_timestamp(Date).

%%随机数
-spec random(Number :: integer()) -> integer().
random(Number) ->
  if
    erlang:is_float(Number) -> NewNumber = erlang:trunc(Number);
    erlang:is_list(Number) -> NewNumber = list_to_integer(Number);
    true -> NewNumber = Number
  end,
  _ = rand:seed(exs1024, {rand:uniform(9999), rand:uniform(9999), rand:uniform(9999)}),
  New_number = rand:uniform(NewNumber),
  ?DEBUG("sys_util random number:~p", [New_number]),
  New_number.


%%两数区间随机数
interval_random_number(Min, Max) ->
  ?DEBUG("interval_random_number,min:~p,max:~p", [Min, Max]),
  RN2 = Max - Min,
  if (RN2 > 10) =:= true
    ->
    RN3 = random(RN2),
    Min + RN3;
    true -> Min
  end.


%% @doc 通过遍历去重
-spec unique_1(List) -> Return when
  List :: list(),
  Return :: list().
unique_1(List) ->
  unique_1(List, []).

unique_1([], ResultList) -> ResultList;
unique_1([H | L], ResultList) ->
  case lists:member(H, ResultList) of
    true -> unique_1(L, ResultList);
    false -> unique_1(L, [H | ResultList])
  end.

%%乱序list
do2(L) ->
  do2(L, []).

do2([], L) ->
  L;
do2(L1, L2) ->
  Len = length(L1),
  if
    Len > 1 ->
      NL = lists:split(rand:uniform(Len - 1), L1),
      {[H1 | T1], [H2 | T2]} = NL,
      NL2 = lists:flatten([T1], [H1 | T2]),
      L11 = lists:append(L2, [H2]),
      do2(NL2, L11);
    true ->
      do2([], lists:append(L2, L1))
  end.

%时间转秒
time_to_second({H, I, S}) ->
  H * 60 * 60 + I * 60 + S.
%获取当前时间
get_now_time() ->
  {_, Now} = local_time(),
  time_to_second(Now).

%%json转list
-spec(json_to_list(String :: string()) -> list()).
json_to_list(String) ->
  Json_list = jsx:decode(String),
  lists:map(fun(Id) -> binary_to_integer(Id) end, Json_list).

%%是否跨天
next_day_verify(Start_at, End_at) ->
  Start_s = time_to_second(Start_at),
  End_s = time_to_second(End_at),
  if
    Start_s > End_s -> true;
    true -> false
  end.



test() ->

  B = ets:select(ets_player_info, [{
    #player_info{
      account = "86-9999057",
      password = '$1',
      channel = '$2',
      _ = '_'
    },
    [],
    ['$_']}]),
  ?DEBUG("info a:~p;b:~p", [B, ets:tab2list(ets_player_info)]),
  ok.








